package com.gqj.meter.controller;

import com.company.mvsdk.api.*;
import com.company.mvsdk.enumeration.EGrabStrategy;
import com.company.mvsdk.enumeration.EImageOutFormat;
import com.company.mvsdk.enumeration.EInterfaceType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

@RestController
@RequestMapping("/camera")
public class CameraController {

    @Value("${cameraTime}")
    public Integer cameraTime;

    static String fileName;
    static Boolean isCreateImage = false;

    @GetMapping("/image")
    public ResponseEntity getImage() {
        System.out.println("开始图片抓取");
        synchronized (isCreateImage) {
            isCreateImage = false;
            photograph();
            if (fileName != null) {
                // 构造Resource对象表示图片文件
                Resource imageResource = new FileSystemResource(fileName); // 根据图片路径构造Resource，可以使用其他实现类，如ClassPathResource等

                // 设置HTTP头信息
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.IMAGE_JPEG); // 设置图片类型，根据实际情况调整
                // 可选：设置其他HTTP头信息，例如Content-Disposition

                // 返回包含图片文件的ResponseEntity
                return new ResponseEntity<>(imageResource, headers, HttpStatus.OK);
            }else{
                return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
            }
        }
    }


    public void photograph() {

        ISystem systemObj = SystemInstance.getInstance();
        ArrayList<DeviceInfo> cameraInfoList = systemObj.enumDevices(EInterfaceType.typeAll);
        if (cameraInfoList == null || cameraInfoList.size() == 0) {
            System.out.println("enumDevicesInfo failed or no camera");
            return;
        }
        // 默认选择第一个
        ICamera cameraObj = systemObj.createCameraHandleByIndex(0);
        // 打开相机
        if (!cameraObj.open()) {
            System.out.println("Open is failed!");
            systemObj.destroyCameraHandle(cameraObj);
            return;
        }
        // 设置图像输出格式为RGB24(不设置的话，图像输出格式默认为裸数据)
        if (!cameraObj.setImageOutFormat(EImageOutFormat.imageOutFormatRGB24)) {
            System.out.println("setImageOutFormat is failed!");
        }
        EventCallBack callBackFunc = new EventCallBack() {
            // Data frame callback method overridden
            // 数据帧回调方法重写
            @Override
            public void frameArgProc(FrameData frameData) {
                // get frame valid or not
                // 获取帧是否有效
                if (!frameData.valid()) {
                    System.out.println("frame is invalid!");
                } else {
                    if (isCreateImage) {
                        return;
                    }
                    isCreateImage = true;
                    // get image block id
                    // 获取图片对应的BlockId
                    System.out.println("Frame blockId : " + frameData.getBlockID());

                    // convert raw data to BufferedImage
                    // 裸数据转换BufferedImage
                    BufferedImage bufferedImage = rawDataToBufferedImage(frameData);


                    // save bitmap to local
                    // 保存bitmap到本地
//                    saveImageToBitmap(image);

                    // save jpeg to local
                    // 保存jpeg到本地
                    saveImageToJpeg(bufferedImage);

                    // 停止拉流
                    if (!cameraObj.stopGrabbing()) {
                        System.out.println("StopGrabbing is failed");

                        // destroy camera handle
                        // 销毁相机句柄
                        systemObj.destroyCameraHandle(cameraObj);
                        return;
                    }

                    // save png to local
                    // 保存png到本地
//                    saveImageToPng(image);
                }
            }
        };
        // register data frame callback method
        // 注册数据帧回调方法
        if (!cameraObj.attachGrabbing(callBackFunc)) {
            System.out.println("attachGrabbing is failed");

            // destroy camera handle
            // 销毁相机句柄
            systemObj.destroyCameraHandle(cameraObj);
            return;
        }


        // startGrabbing
        // 开始拉流
        if (!cameraObj.startGrabbing(EGrabStrategy.grabStrartegySequential)) {
            System.out.println("startGrabbing is failed");

            // destroy camera handle
            // 销毁相机句柄
            systemObj.destroyCameraHandle(cameraObj);
            return;
        }


        // delay 2 second
        // 延迟2秒

        try {
            Thread.sleep(cameraTime);
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        // Unregister data frame callback method
        // 去注册数据帧回调方法
        if (!cameraObj.detachGrabbing(callBackFunc)) {
            System.out.println("detachGrabbing is failed");
        }

        // stopGrabbing
        // 停止拉流
        if (!cameraObj.stopGrabbing()) {
            System.out.println("StopGrabbing is failed");

            // destroy camera handle
            // 销毁相机句柄
            systemObj.destroyCameraHandle(cameraObj);
            return;
        }

        // close camera
        // 关闭相机
        if (!cameraObj.close()) {
            System.out.println("Close is failed");

            // destroy camera handle
            // 销毁相机句柄
            systemObj.destroyCameraHandle(cameraObj);
            return;
        }

        // destroy camera handle
        // 销毁相机句柄
        systemObj.destroyCameraHandle(cameraObj);
    }

    public static BufferedImage rawDataToBufferedImage(FrameData frameData) {
//    	DataBufferByte dataBuffer = new DataBufferByte(frameData.getImage(), frameData.getImageSize());
        byte image[] = new byte[frameData.getImageSize() * 3];
        DataBufferByte dataBuffer = new DataBufferByte(image, image.length);
        System.arraycopy(frameData.getImage(), 0, image, 0, frameData.getImageSize());
        ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
        ComponentColorModel colorModel = new ComponentColorModel(cs, false, false, Transparency.OPAQUE, DataBufferByte.TYPE_BYTE);
        int[] bOffs = {0, 1, 2};
        WritableRaster raster = Raster.createInterleavedRaster(dataBuffer, frameData.getImageWidth(), frameData.getImageHeight(), frameData.getImageWidth() * 3, 3, bOffs, null);
        return new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
    }

    // 保存jpeg到本地
    public static void saveImageToJpeg(BufferedImage image) {
        // get user's current working directory
        // 获取用户当前工作目录
        String userDir = System.getProperty("user.dir");
        System.out.println("userDir" + userDir);
        //String userDir = "D:/jar/";

        File directory = new File(userDir);
        if (!directory.exists()) {
            System.out.println(userDir + " is no exist");
            return;
        }

        String imageName = "Pic_camera.jpeg";

        File descFile = new File(userDir + "/" + imageName);
        fileName = descFile.getAbsolutePath();
        if (descFile.exists()) {
            descFile.delete();
        }

        ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next();
        ImageWriteParam param = writer.getDefaultWriteParam();
        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        param.setCompressionQuality(1.0F); //Value range 0.0F~1.0F (1.0F Highest quality)
        try {
            writer.setOutput(new FileImageOutputStream(descFile));
            writer.write(null, new IIOImage(image, null, null), param);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println("Save " + imageName + " to " + userDir + " successfully!");
    }
}
